/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



#ifndef _THREAD_H__
#define _THREAD_H__

#include <vector>
#include <queue>
using namespace std;

#include <pthread.h>

/**
 *  @brief Base class for multi-threading. Cannot be used directly; must be implemented by subclasses for specific functionality. 
 *      1，Starting a single thread.
 *      2，Starting a thread pool.
 *      3，Step-by-step execution threads.
 *      4，Repeatedly executed threads.
 */
class CThread {
public:
	CThread();
	virtual ~CThread();
    /**
     * @brief Starts the thread.
     * @param arg A pointer to user data.
     * @param bJoinable  Whether the thread is joinable or detached.
     * @return true if success,false if failed
     */
	bool Start(void * arg, bool bJoinable = true);
    /**
     * @brief Checks if the thread is currently running.
     * @return true if running, false if finished
     */
	bool IsRunning();
    /**
     * @brief Sets stop flag
     * @return
     */
	virtual void Stop();
    /**
     * @brief Gets id of thread
     * @return id of thread
     */
	pthread_t GetThreadId(){return m_thread;}
    /**
     * @brief Waits for the thread to finish.
     * @param[out] ppRetval Return value of the thread.
     * @return 0 if success，otherwise failed.
     */
	int Join(void **ppRetval);
protected:
    /**
     * @brief Execution function of the thread.
     * @param arg A pointer to user data.
     */
	void Run(void * arg);
    /**
     * @brief Entry function of the thread.
     * @param arg A pointer to user data.
     * @return null (return value has no effect).
     */
	static void * EntryPoint (void *);
    /**
     * @brief Anything you want to be executed before Execute()
     */
	virtual void Setup();
    /**
     * @brief Specific implementation function of the thread (to be implemented by subclasses).
     * @param arg A pointer to user data.
     */
	virtual void Execute(void *) = 0;
    /**
     * @brief Gets pointer of user data
     * @return A pointer to user data.
     */
	void * GetArg() const {return m_arg;}
    /**
     * @brief Sets pointer of user data
     * @param a A pointer to user data.
     */
	void SetArg(void * a) {m_arg = a;}
    /**
     * @brief Gets stop flag
     * @return true if stop, false if running
     */
	bool GetStopFlag();
    /**
     * @brief Sets stop flag
     */
	void SetStopFlag();
    /**
     * @brief Resets stop flag
     */
	void ResetStopFlag();
private:
	void * m_arg;
	bool m_bStop;
	pthread_t m_thread;
	pthread_mutex_t m_mutexStop;
private:
    void AddSelfToList();
    void RemoveSelfFromList();
    static pthread_mutex_t m_mutexRun;
    static vector<void*> m_ThreadList;
};

/**
 * @brief defines class of thread pool
 */
class CThreadPool
{
    /**
     * Maximum number of threads in the pool. This thread pool is used for Cordova network requests.
     * Network requests use a domain-based grouped thread pool, where each domain can have up to 20 threads processing requests in the background.
     */
    static const int MAX_THREAD_NUMBER_BOUNDARY = 20;
public:
	CThreadPool();
	~CThreadPool();
    /**
     * @brief Initial size of the thread pool.
     * @param nSize number of threads
     */
	void SetPoolSize(const int nSize);
    /**
     * @brief add task
     * @param arg data of task
     */
	void AddTask(const void* arg);
    /**
     * @brief start thread pool
     * @param arg pointer of use data
     * @return true if success, false if failed
     */
	bool Start(void* arg);
    /**
     * @brief stop thread pool
     */
	virtual void Stop();
    /**
     * @brief Gets the number of idle threads in the pool.
     * @return int Number of idle threads.
     */
    int GetWaitingThreads();
    /**
     * @brief Gets the current number of threads in the pool.
     * @return Current number of threads in the pool.
     */
    int GetCurPoolSize();
protected:
     /**
     * @brief Execution function of the thread.
     * @param arg A pointer to user data.
     */
	void Run(void* arg);
    /**
     * @brief Specific implementation function of the thread (to be implemented by subclasses).
     * @param arg A pointer to user data.
     */
	virtual void Execute(const void*,const int, void*) = 0;
    /**
     * @brief Specific function to execute the task (can be implemented by either the subclass or the parent class).
     * @param arg pointer of use data
     */
	virtual void LoopTask(void *arg);
    /**
     * @brief Gets pointer of use data
     * @return pointer of use data
     */
	void* GetArg()const {return m_arg;}
    /**
     * @brief Sets pointer of use data
     * @param a pointer of use data
     */
	void SetArg(void* a) {m_arg = a;}
    /**
     * @brief Thread creation function.
     * @param pObj Passes the current object.
     * @return null (return value has no effect).
     */
	static void* EntryPoint(void*);
    /**
     * @brief Gets stop flag
     * @return true if stop, false if running
     */
	bool GetStopFlag();
    /**
     * @brief Sets stop flag
     */
	void SetStopFlag();
    /**
     * @brief Resets stop flag
     */
	void ResetStopFlag();
    
private:
	const void* GetTask(int & nTotalTask);
	void* m_arg;
	std::atomic<bool> m_bStop{false};
	queue<const void*> m_taskQue;
    /**Initial number of threads. This count remains unchanged after initialization, maintaining the minimum number in the pool.*/
	std::atomic<int> m_nPoolSize{0};
    /**Current number of threads. The thread count automatically increases based on the task queue, with the initial count as the minimum.*/
    std::atomic<int> m_nCurPoolSize{0};
    /**Current number of idle threads (i.e., threads waiting for tasks).*/
    std::atomic<int> m_nWaitingThread{0};
	pthread_mutex_t m_mutexCond;
	pthread_cond_t m_cond;
	pthread_mutex_t m_mutexTask;
    /**
     * @brief Processes the task.
     */
	void DealTask();
    bool StartThread();
    /**
     * @brief Gets stop flag
     * @return true if stop, false if Non-stop
     */
    bool GetThreadStop();
    /**
     * @brief Initialization function called when the thread starts (to be implemented by subclasses, typically used for memory allocation for the thread).
     * @return Returns a memory pointer.
     */
	virtual void* InitThreadData() = 0;
    /**
     * @brief Function executed before the thread ends (to be implemented by subclasses, typically used to clean up memory allocated during initialization).
     * @param pArg Pointer returned by thread initialization.
     */
	virtual void DeInitThreadData(void* pArg) = 0;
};

/**
 * @brief Step-by-step execution thread.
 */
class CThreadStep : public CThread
{
public:
	CThreadStep();
	virtual ~CThreadStep();
    /**
     * @brief Checks if the thread is idle.
     * @return true if idle, false if not idle.
     */
	bool IsIdle();
    /**
     * @brief Executes the next step.
     */
	void NextStep();
    /**
     * @brief Sets stop flag
     */
	virtual void Stop();
protected:
    /**
     * @brief Specific implementation function of the thread (to be implemented by subclasses).
     * @param arg A pointer to user data.
     */
	virtual void Execute(void *arg);
    /**
     * @brief Executes the next step (to be implemented by subclasses).
     * @param arg A pointer to user data
     */
	virtual void StepTask(void *arg) = 0;
private:
	pthread_mutex_t m_mutexStep;
	pthread_cond_t m_cond;
};

class CThreadLoop : public CThread
{
public:
	CThreadLoop();
	virtual ~CThreadLoop();
    /**
     * @brief Sets stop flag
     */
	virtual void Stop();
    /**
     * @brief pause task
     */
	void Pause();
    /**
     * @brief Restarts task
     */
	void Resume();
    /**
     * @brief Get status of pause
     * @return true if pause,false if running
     */
	bool GetPauseStatus();
    /**
     * @brief Checks if the thread is idle.
     * @return true if idle, false if not idle.
     */
	bool IsIdle();
protected:
    /**
     * @brief Specific implementation function of the thread (to be implemented by subclasses).
     * @param arg A pointer to user data.
     */
	virtual void Execute(void *arg);
    /**
     * @brief Specific execution function of the thread (to be implemented by subclasses).
     * @param arg A pointer of user data
     */
	virtual void LoopTask(void *arg) = 0;
    /**
     * @brief Sets the thread sleep time.
     * @param nMilliSec Time in milliseconds.
     */
	void SetSleepTime(int nMilliSec){m_nSleepTime = nMilliSec;}
private:
	pthread_mutex_t m_mutexPause;
	pthread_mutex_t m_mutexLoop;
	bool m_bPause;
	int m_nSleepTime; //milli-seconds
};

#endif //_THREAD_H__
